﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Security;

namespace Microsoft.Cryptography.WCF
{
    /// <summary>
    /// This class ist only a wrapper around out-of-the-box SecurityAlgorithmSuites, which 
    /// could be used as a workaround to suppress some error messages. The WCF-framework
    /// rises exceptions, if a SecurityAlgorithmSuite with RSA-SHA256 ist used in an 
    /// Asymmetric scenario. These exceptions are only raised, if the type of the used 
    /// SecurityAlgorithmSuite is one of the out-of-thebox SecurityAlgorithmSuites, which
    /// are using RSA-SHA256.
    /// 
    /// This exception is thrown, because of a validation rule in “System.ServiceModel.Dispatcher.SecurityValidationBehavior.RsaSHA256AlgorithmSuiteRule.ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding)”. The code-snippet in the Reflector looks like:
    /// public static void ValidateSecurityBinding(SecurityBindingElement sbe, Binding binding)
    /// {
    ///     if (sbe != null)
    ///     {
    ///         bool flag = false;
    ///         if (SecurityAlgorithmSuite.IsRsaSHA256(sbe.DefaultAlgorithmSuite))
    ///         {
    ///             foreach (SecurityTokenParameters parameters in new AuthenticationSecurityTokenParametersEnumerable(sbe))
    ///             {
    ///                 if (parameters is SecureConversationSecurityTokenParameters)
    ///                 {
    ///                     SecureConversationSecurityTokenParameters parameters2 = parameters as SecureConversationSecurityTokenParameters;
    ///                     ValidateSecurityBinding(parameters2.BootstrapSecurityBindingElement, binding);
    ///                 }
    ///                 if (parameters.HasAsymmetricKey)
    ///                 {
    ///                     flag = true;
    ///                     break;
    ///                 }
    ///             }
    ///             if (flag)
    ///             {
    ///                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString("RsaSHA256NotSupported", new object[] { binding.Name, binding.Namespace, sbe.DefaultAlgorithmSuite })));
    ///             }
    ///         }
    ///     }
    /// }
    /// </summary>
    public class SecurityAlgorithmSuiteWrapper : SecurityAlgorithmSuite
    {
        SecurityAlgorithmSuite _sas;

        /// <summary>
        /// Creates a new instance of the wrapper around out-of-the-box SecurityAlgorithmSuites, which 
        /// could be used as a workaround to suppress some error messages. The WCF-framework
        /// rises exceptions, if a SecurityAlgorithmSuite with RSA-SHA256 ist used in an 
        /// Asymmetric scenario.
        /// </summary>
        /// <param name="sas">The <see cref="System.ServiceModel.Security.SecurityAlgorithmSuite"/></param>
        public SecurityAlgorithmSuiteWrapper(SecurityAlgorithmSuite sas) 
        {
            _sas = sas;
        }

        private SecurityAlgorithmSuiteWrapper()
        {
        }

        /// <summary>
        /// Gets the default asymmetric key wrap algorithm as a string
        /// </summary>
        public override string DefaultAsymmetricKeyWrapAlgorithm
        {
            get
            {
                return _sas.DefaultAsymmetricKeyWrapAlgorithm;
            }
        }

        /// <summary>
        /// Gets the default asymmetric signature algorithm as a string
        /// </summary>
        public override string DefaultAsymmetricSignatureAlgorithm
        {
            get
            {

                return _sas.DefaultAsymmetricSignatureAlgorithm;
            }
        }

        /// <summary>
        /// Gets the default canonicalization algorithm as a string
        /// </summary>
        public override string DefaultCanonicalizationAlgorithm
        {
            get { return _sas.DefaultCanonicalizationAlgorithm; }
        }

        /// <summary>
        /// Gets the default digest algorithm as a string
        /// </summary>
        public override string DefaultDigestAlgorithm
        {
            get { return _sas.DefaultDigestAlgorithm; }
        }

        /// <summary>
        /// Gets the default encryption algorithm as a string
        /// </summary>
        public override string DefaultEncryptionAlgorithm
        {
            get { return _sas.DefaultEncryptionAlgorithm; }
        }

        /// <summary>
        /// Gets the default encryption key derivation length
        /// </summary>
        public override int DefaultEncryptionKeyDerivationLength
        {
            get { return _sas.DefaultEncryptionKeyDerivationLength; }
        }

        /// <summary>
        /// Gets the default signature key derivation length
        /// </summary>
        public override int DefaultSignatureKeyDerivationLength
        {
            get { return _sas.DefaultSignatureKeyDerivationLength; }
        }

        /// <summary>
        /// Gets the default symmetric key length
        /// </summary>
        public override int DefaultSymmetricKeyLength
        {
            get { return _sas.DefaultSymmetricKeyLength; }
        }

        /// <summary>
        /// Gets the default symmetric key wrap algorithm
        /// </summary>
        public override string DefaultSymmetricKeyWrapAlgorithm
        {
            get { return _sas.DefaultSymmetricKeyWrapAlgorithm; }
        }

        /// <summary>
        /// Gets the default symmetric signature algorithm
        /// </summary>
        public override string DefaultSymmetricSignatureAlgorithm
        {
            get { return _sas.DefaultSymmetricSignatureAlgorithm; }
        }

        /// <summary>
        /// Returns a boolean flag, which indicates whether the specified length is supported for asymmetric keys
        /// </summary>
        /// <param name="length">The specified length of the asymmetric key</param>
        /// <returns>Returns a boolean flag, which indicates whether  the specified length is supported for asymmetric keys</returns>
        public override bool IsAsymmetricKeyLengthSupported(int length)
        {
            return _sas.IsAsymmetricKeyLengthSupported(length);
        }

        /// <summary>
        /// Returns a boolean flag, which indicates whether the specified length is supported for symmetric keys
        /// </summary>
        /// <param name="length">The specified length of the symmetric key</param>
        /// <returns>Returns a boolean flag, which indicates whether  the specified length is supported for symmetric keys</returns>
        public override bool IsSymmetricKeyLengthSupported(int length)
        {
            return _sas.IsSymmetricKeyLengthSupported(length);
        }
    }
}
